import '../libs/CSS2DRenderer';
import { EventListener } from "../libs/EventListener";


export function Renderer(container) {

    /**
     * width
     * height
     * */
    this.width = container.clientWidth;
    this.height = container.clientHeight;

    /**
     * ENABLED
     * */
    this.ENABLED = true;


    /**
     * element
     * */
    this.domElement = document.createElement('div');
    this.domElement.className = 'vr-panoramic-renderer';
    this.domElement.style.width = this.width + 'px';
    this.domElement.style.height = this.height + 'px';
    this.domElement.style.position = 'relative';
    this.domElement.style.overflow = 'hidden';
    // append
    container.appendChild(this.domElement);


    /**
     * renderer
     * */
    this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, preserveDrawingBuffer: true });
    this.renderer.setClearColor(0xffffff, 0);
    this.renderer.setPixelRatio(window.devicePixelRatio);
    this.renderer.setSize(this.width, this.height);
    this.renderer.sortObjects = true;
    this.renderer.autoClear = false; // To allow render overlay on top of sprited sphere
    // append
    this.domElement.appendChild(this.renderer.domElement);


    // div renderer
    this.divRenderer = new THREE.CSS2DRenderer();
    this.divRenderer.setSize(this.width, this.height);
    this.divRenderer.domElement.style.position = 'absolute';
    this.divRenderer.domElement.style.top = '0px';
    // append
    this.domElement.appendChild(this.divRenderer.domElement);


    /**
     * scene
     * */
    this.scene = new THREE.Scene();


    /**
     * camera
     * */
    this.camera = new THREE.PerspectiveCamera(50, this.width / this.height, 1, 10000);
    //已z轴为高度
    this.camera.up.set(0, 0, 1);


    /**
     * resize
     * */
    this.resize = (width, height) => {

        this.width = width;
        this.height = height;
        //
        this.domElement.style.width = this.width + 'px';
        this.domElement.style.height = this.height + 'px';
        //
        this.camera.aspect = this.width / this.height;
        this.camera.updateProjectionMatrix();

        this.renderer.setSize(this.width, this.height);
        this.divRenderer.setSize(this.width, this.height);

        this.render();

    };


    /**
     * add
     * */
    this.add = (object) => {
        this.scene.add(object);
        return this;
    };


    /**
     * clear
     * */
    this.clear = () => {
        this.renderer.clear();
        this.renderer.clearDepth();
    };


    /**
     * render
     * */
    this.render = () => {
        this.clear();
        this.emit('render');
        this.renderer.render(this.scene, this.camera);
        this.divRenderer.render(this.scene, this.camera);
    };
    //
    let __RENDER__ = () => {
        if (this.ENABLED) this.render();
        requestAnimationFrame(__RENDER__);
    };
    __RENDER__();


    // 坐标转换
    this.pointToVector3 = (() => {
        //
        const raycaster = new THREE.Raycaster();
        const quaternion = new THREE.Quaternion();
        const euler = new THREE.Euler();
        //
        const pointer = new THREE.Vector2();
        const vector3 = new THREE.Vector3();

        return (x, y) => {
            //
            pointer.x = (x / this.domElement.clientWidth) * 2 - 1;
            pointer.y = - (y / this.domElement.clientHeight) * 2 + 1;

            // 通过摄像机和鼠标位置更新射线
            raycaster.setFromCamera(pointer, this.camera);

            // children
            const children = [];
            this.scene.traverse(object => {
                if (object.type === 'Sphere') {
                    children.push(object);
                }
            });


            // intersects
            let intersects = raycaster.intersectObjects(children).filter(mesh => {
                return mesh.object.parent.visible;
            })[0];

            //
            if (intersects) {
                // parent 
                const rotation = intersects.object.parent.rotation;
                //
                euler.set(-rotation.x, 0, -rotation.z, 'ZXY');
                quaternion.setFromEuler(euler);
                //
                vector3.copy(intersects.point);
                vector3.applyQuaternion(quaternion);
                //
                return { x: vector3.x, y: vector3.y, z: vector3.z };
            }

            return null;
        }

    })();


    // vector3ToEulerAngle
    this.vector3ToEulerAngle = (x, y, z) => {

        if (x instanceof Array) {
            z = x[2];
            y = x[1];
            x = x[0];
        }
        else if (typeof x === 'object') {
            z = x.z;
            y = x.y;
            x = x.x;
        }

        // 距离
        let d = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));

        // 倾斜角
        let phi = Math.round(Math.atan2(d, -z) * (180 / Math.PI));
        if (phi < 0) phi += 360;
        if (phi > 180) phi -= 360;

        // 水平角
        let theta = Math.round(Math.atan2(x, y) * (180 / Math.PI));
        if (theta < 0) theta += 360;

        return {
            phi: Math.abs(phi),
            roll: 0,
            theta: Math.abs(theta)
        }
    }
}

Renderer.prototype = Object.assign(Renderer.prototype, EventListener.prototype);
Renderer.prototype.constructor = Renderer;
